`timescale 1ns / 1ps


module dds_ctrl
#(parameter T =20000)

(
    input   wire            sys_clk_p           ,
    input   wire            sys_rst_n           ,
    input   wire            duty_adj            ,
    input   wire            iq_adj              ,
    input   wire            a_adj               ,
    input   wire            f_add_adj           ,
    input   wire            f_sub_adj           ,
    input   wire            w_adj               ,
    input   wire  [7:0]     rom_data            ,             
	output  reg   [11:0]    f_word = 10'd0      ,
    output  reg   [15:0]    p_word = 15'd0      ,
    output  reg             mode   = 1'b0       ,
    output  wire            led                 ,
    output  reg   [9:0]     dac_out          
    );
    
    reg [3:0]   base_addr       =  4'd0     ;    
    reg [1:0]   base_A          =  2'b00    ;
    reg [1:0]   a_st            =  2'b00    ;
    
    reg [9:0]   addr_r          =  0        ;   
    reg [3:0]   f_st            =  0        ; 
        
    wire        a_flag                      ;
    wire        duty_flag                   ;
    wire        f_sub_flag                  ;
    wire        f_add_flag                  ;
    wire        mode_flag                   ;                    
    wire        f_flag                      ;
    wire        w_flag                      ;
    
   // 波形文件地址的基地址
    reg [3:0] addr_st = 0 ;
    
    always @ (posedge sys_clk_p )
        begin
            if (~sys_rst_n)
                begin                 
                    base_addr <=0;
                    addr_st   <=0;  
                end    
            else 
            begin 
                case ( addr_st)
                
                0: begin 
                    base_addr <=  0  ;
                    if ( w_flag )
                        addr_st <= addr_st + 1 ;
                    else  ;                                                                         
                end 
               
                1: begin                 
                    base_addr <=  1  ;
                    if ( w_flag )
                        addr_st <= addr_st + 1 ;
                    else  ;                                                
                end                
               
                2: begin 
                    base_addr <=  2  ;
                    if ( w_flag )
                        addr_st <= addr_st + 1 ;
                    else  ;                                 
                end 

                3: begin 
                    base_addr <=  5  ;                                                                                
                    if ( w_flag )
                        addr_st <= 0 ;
                    else  if ( duty_flag) 
                        addr_st <= addr_st +3 ;
                    else ;
                end 
               
                4: begin 
                    base_addr <=  6  ;                                                                                
                    if ( w_flag )
                        addr_st <= 0 ;
                    else  if ( duty_flag) 
                        addr_st <= addr_st +1 ;
                    else ;
                end 
                
                5: begin 
                    base_addr <=  7  ;                                                                                
                    if ( w_flag )
                        addr_st <= 0 ;
                    else  if ( duty_flag) 
                        addr_st <= addr_st +1 ;
                    else ;
                end                 
               
                6: begin 
                    base_addr <=  8  ;                                                                                
                    if ( w_flag )
                        addr_st <= 0 ;
                    else  if ( duty_flag) 
                        addr_st <= addr_st +1 ;
                    else ;
                end                
               
                7: begin 
                    base_addr <=  9  ;                                                                                
                    if ( w_flag )
                        addr_st <= 0 ;
                    else  if ( duty_flag) 
                        addr_st <= addr_st +1 ;
                    else ;
                end                
               
                8: begin 
                    base_addr <=  10  ;                                                                                
                    if ( w_flag )
                        addr_st <= 0 ;
                    else  if ( duty_flag) 
                        addr_st <= addr_st +1 ;
                    else ;
                end 
                
                9: begin 
                    base_addr <=  11 ;                                                                                
                    if ( w_flag )
                        addr_st <= 0 ;
                    else  if ( duty_flag) 
                        addr_st <= addr_st +1 ;
                    else ;
                end                

                10: begin 
                    base_addr <=  12 ;                                                                                
                    if ( w_flag )
                        addr_st <= 0 ;
                    else  if ( duty_flag) 
                        addr_st <= addr_st +1 ;
                    else ;
                end                
               
                11: begin 
                    base_addr <=  13  ;                                                                                
                    if ( w_flag )
                        addr_st <= 0 ;
                    else  if ( duty_flag) 
                        addr_st <= 5 ;
                    else ;
                end 
                
                default :  begin  
                
                    base_addr <=0  ;
                    addr_st   <=0  ;                                                  
                end 
                
            endcase                 
            end 
        end 
    
    //  波形信号的放大倍数

    always @ (posedge sys_clk_p )
        begin
            if (~sys_rst_n)
                begin
                    base_A <=1;
                    a_st   <=0;
                end
            else 
            begin case (a_st)
            
                    0:  begin
                            base_A <=1;
                            a_st   <=1;
                        end
                
                    1:  begin 
                            if (a_flag)
                                begin 
                                    a_st<=2 ;
                                    base_A <=2;
                                end 
                            else 
                                begin 
                                    a_st<=1 ;
                                    base_A <=1;				
                                end 			
                        end 
                    
                    2: begin    
                            if (a_flag)   
                                begin    
                                    a_st<=3;   
                                    base_A <=3;   
                                end    
                            else 
                                begin    
                                a_st<=2;   
                                base_A <=2;   
                                end 			   
                        end 

                    3: begin    
                            if (a_flag)   
                                begin    
                                    a_st<=1;   
                                    base_A <=1;   
                                end    
                            else 
                                begin    
                                a_st<=3;   
                                base_A <=3;   
                                end 			   
                        end                         
                                                                 
                    endcase   
                end	 
        end  
    
    //  产生波形信号放大
    
    always @ (posedge sys_clk_p )
        begin
            if (~sys_rst_n) 
                dac_out <=0 ;
            else 
                dac_out<= rom_data * base_A ;
        end  
    // 频率控制字调节           
    always @ (posedge sys_clk_p   )
        begin
            if ( ~sys_rst_n )                 
                    f_word <= 1;
            else begin 
                        if ( f_add_flag )
                        begin 
                            if ( f_word<1023)
                                f_word <= f_word +1 ;
                            else 
                                f_word <= f_word    ;
                        
                        end 
                    
                        else   begin  
                            if ( f_sub_flag )
                                 begin 
                                    if ( f_word>1)
                                        f_word <= f_word -1     ;
                                    else 
                                        f_word <= f_word        ;
                                
                                  end 
                            else ;
                        end   
            
                end 
                                        
        end 
        
    // 信号发生通道选择    
    always @ (posedge sys_clk_p )
        begin
            if (~sys_rst_n ) 
                mode <=0                ;
            else 
            begin 
                 if (mode_flag)
                    mode <=     ~mode   ;
                else  
                    mode  <=    mode    ;
            end 
        end 
    // 通道指示信号    
    assign  led = mode ;  
    
    // 相位控制字产生
    always @ (posedge sys_clk_p )
        begin 
            if ( ~sys_rst_n )
                p_word  <=  16'd0 ; 
            else 
                p_word  <= {base_addr,12'd0 } ;           
        end 
    
    // 按键消除抖动
    
    key_process 
    #(.T(T))
    key_process_inst0(    
        .clk         ( sys_clk_p            ) ,
        .rst_n       ( sys_rst_n            ) ,    
        .key_switch  ( a_adj                ) ,   
        .flag_switch ( a_flag               )    
    );  

    key_process
    #(.T(T))
    key_process_inst4(    
        .clk         ( sys_clk_p            ) ,
        .rst_n       ( sys_rst_n            ) ,    
        .key_switch  ( iq_adj               ) ,   
        .flag_switch ( mode_flag            )    
    ); 
    
    key_process 
    #(.T(T))
    key_process_inst5(    
        .clk         ( sys_clk_p            ) ,
        .rst_n       ( sys_rst_n            ) ,    
        .key_switch  ( f_sub_adj            ) ,   
        .flag_switch ( f_sub_flag           )    
    ); 
   
    
    key_process
    #(.T(T))
    key_process_inst1(    
        .clk         ( sys_clk_p            ) ,
        .rst_n       ( sys_rst_n            ) ,    
        .key_switch  ( duty_adj             ) ,   
        .flag_switch ( duty_flag            )    
    );  
    
    key_process
    #(.T(T))
    key_process_inst2(    
        .clk         ( sys_clk_p            ) ,
        .rst_n       ( sys_rst_n            ) ,    
        .key_switch  ( f_add_adj            ) ,   
        .flag_switch ( f_add_flag           )    
    );  
    
    key_process 
    #(.T(T))
    key_process_inst3(    
        .clk         ( sys_clk_p            ) ,
        .rst_n       ( sys_rst_n            ) ,    
        .key_switch  ( w_adj                ) ,   
        .flag_switch ( w_flag               )    
    );  
      
endmodule
